/*
 * SPDX-FileCopyrightText: 2024 Andrew Gunnerson
 * SPDX-License-Identifier: GPL-3.0-only
 */

package com.sanji.audio_test.rule

import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.res.TypedArrayUtils
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.sanji.audio_test.ContactGroupInfo
import com.sanji.audio_test.ContactInfo
import com.sanji.audio_test.R
import com.sanji.audio_test.rule.RecordRulesAdapter.CustomViewHolder
import kotlin.math.absoluteValue

/**
 * 录音规则适配器
 * 用于在RecyclerView中显示和管理录音规则列表
 * @param context 上下文
 * @param listener 监听器
 */
internal class RecordRulesAdapter(
    private val context: Context,
    private val listener: Listener,
) : RecyclerView.Adapter<CustomViewHolder?>() {
    
    /**
     * 监听器接口
     * 定义规则变化和选择相关的回调方法
     */
    interface Listener {
        /**
         * 当规则发生变化时调用
         * @param rules 更新后的规则列表
         */
        fun onRulesChanged(rules: List<RecordRule>)

        /**
         * 当规则被选中时调用
         * @param position 规则位置
         * @param rule 选中的规则
         * @param isDefault 是否为默认规则
         */
        fun onRuleSelected(position: Int, rule: RecordRule, isDefault: Boolean)
    }

    /**
     * 自定义ViewHolder类
     * 用于持有和管理列表项视图
     */
    internal inner class CustomViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        // 图标框架视图
        private val iconFrame: View = view.findViewById(androidx.preference.R.id.icon_frame)
            ?: view.findViewById(android.R.id.icon_frame)
        // 标题视图
        private val titleView = view.findViewById<TextView>(android.R.id.title)
        // 摘要视图
        private val summaryView = view.findViewById<TextView>(android.R.id.summary)

        // 标题属性
        var title: CharSequence
            get() = titleView.text
            set(text) {
                titleView.text = text
            }

        // 摘要属性
        var summary: CharSequence
            get() = summaryView.text
            set(text) {
                summaryView.text = text
            }

        init {
            iconFrame?.isVisible = false

            // 我们目前没有超过默认的4行限制，但如果实现了更多条件，未来可能会超过。
            summaryView.maxLines = Integer.MAX_VALUE

            // 设置点击监听器
            view.setOnClickListener {
                val position = bindingAdapterPosition
                listener.onRuleSelected(position, rules[position], isDefaultRule(position))
            }
        }
    }

    // 规则列表
    private var rules: ArrayList<RecordRule> = arrayListOf()
        set(newRules) {
            val diff = DiffUtil.calculateDiff(
                object : DiffUtil.Callback() {
                    override fun getOldListSize(): Int = field.size

                    override fun getNewListSize(): Int = newRules.size

                    // 索引标识规则。如果规则的位置发生变化，则需要重新渲染以获得新标题。
                    override fun areItemsTheSame(
                        oldItemPosition: Int,
                        newItemPosition: Int,
                    ): Boolean = oldItemPosition == newItemPosition

                    override fun areContentsTheSame(
                        oldItemPosition: Int,
                        newItemPosition: Int,
                    ): Boolean = field[oldItemPosition] == newRules[newItemPosition]
                },
                true,
            )

            field = newRules

            diff.dispatchUpdatesTo(this)
        }
    // 联系人映射
    private var contacts: Map<String, ContactInfo?> = emptyMap()
    // 联系人组映射
    private var groups: Map<Long, ContactGroupInfo?> = emptyMap()

    // 偏好设置布局资源
    @SuppressLint("PrivateResource", "RestrictedApi")
    private val preferenceLayout = run {
        val defStyleAttr = TypedArrayUtils.getAttr(
            context,
            androidx.preference.R.attr.preferenceStyle,
            android.R.attr.preferenceStyle,
        )
        val attrs = context.obtainStyledAttributes(
            null,
            androidx.preference.R.styleable.Preference,
            defStyleAttr,
            0,
        )
        try {
            TypedArrayUtils.getResourceId(
                attrs,
                androidx.preference.R.styleable.Preference_layout,
                androidx.preference.R.styleable.Preference_android_layout,
                androidx.preference.R.layout.preference,
            )
        } finally {
            attrs.recycle()
        }
    }

    /**
     * 创建ViewHolder
     */
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
        val item = LayoutInflater.from(context).inflate(preferenceLayout, parent, false)
        return CustomViewHolder(item)
    }

    /**
     * 绑定ViewHolder数据
     */
    override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
        val rule = rules[position]

        // 设置标题
        holder.title = if (isDefaultRule(position)) {
            context.getString("Default rule")
        } else {
            context.getString("Rule %d", position + 1)
        }

        // 构建并设置摘要
        holder.summary = buildString {
            when (rule.callNumber) {
                RecordRule.CallNumber.Any -> {}
                is RecordRule.CallNumber.Contact -> {
                    val contact = contacts[rule.callNumber.lookupKey]

                    append(context.getString(
                        "Contact: %s",
                        contact?.displayName ?: rule.callNumber.lookupKey,
                    ))
                    append('\n')
                }
                is RecordRule.CallNumber.ContactGroup -> {
                    val group = groups[rule.callNumber.rowId]

                    val msg = if (group?.title != null) {
                        context.getString(
                            "Contact group: %1$s (%2$s)",
                            group.title,
                            group.accountName
                                ?: context.getString("Local group"),
                        )
                    } else {
                        context.getString(
                            "Contact group: %s",
                            rule.callNumber.sourceId ?: rule.callNumber.rowId.toString(),
                        )
                    }
                    append(msg)
                    append('\n')
                }
                RecordRule.CallNumber.Unknown -> {
                    append(context.getString("Match: Unknown numbers"))
                    append('\n')
                }
            }

            // 添加通话类型信息
            val typeMsgId = when (rule.callType) {
                RecordRule.CallType.ANY -> 0
                RecordRule.CallType.INCOMING -> "Type: Incoming call"
                RecordRule.CallType.OUTGOING -> "Type: Outgoing call"
                RecordRule.CallType.CONFERENCE -> "Type: Conference call"
            }
            if (typeMsgId != 0) {
                append(context.getString(typeMsgId))
                append('\n')
            }

            // 添加SIM卡槽信息
            val simSlotMsg = when (rule.simSlot) {
                RecordRule.SimSlot.Any -> null
                is RecordRule.SimSlot.Specific ->
                    context.getString("SIM slot: %d", rule.simSlot.slot)
            }
            simSlotMsg?.let {
                append(it)
                append('\n')
            }

            // 添加操作信息
            val actionMsgId = when (rule.action) {
                RecordRule.Action.SAVE -> "Action: Save recording"
                RecordRule.Action.DISCARD -> "Action: Discard recording"
                RecordRule.Action.IGNORE -> "Action: Ignore recording"
            }
            append(context.getString(actionMsgId))
        }
    }

    /**
     * 获取项目数量
     */
    override fun getItemCount(): Int = rules.size

    /**
     * 设置可显示的规则
     * @param displayableRules 可显示的规则数据
     */
    fun setDisplayableRules(displayableRules: DisplayableRules) {
        rules = ArrayList(displayableRules.rules)
        contacts = displayableRules.contacts
        groups = displayableRules.groups
    }

    /**
     * 判断是否为默认规则
     * @param position 规则位置
     * @return 是否为默认规则
     */
    internal fun isDefaultRule(position: Int) = position == rules.size - 1

    /**
     * 处理规则移动
     * @param fromPosition 起始位置
     * @param toPosition 目标位置
     */
    internal fun onRuleMove(fromPosition: Int, toPosition: Int) {
        if ((fromPosition - toPosition).absoluteValue == 1) {
            val rule = rules[fromPosition]
            rules[fromPosition] = rules[toPosition]
            rules[toPosition] = rule
        } else if (fromPosition != toPosition) {
            val rule = rules.removeAt(fromPosition)
            rules.add(toPosition, rule)
        }

        notifyItemChanged(fromPosition)
        if (fromPosition != toPosition) {
            notifyItemChanged(toPosition)
        }
        // 即使两个位置相同也需要调用此方法。否则，缓慢拖拽规则到另一个规则上会取消当前拖拽动作并开始新的拖拽。
        notifyItemMoved(fromPosition, toPosition)

        if (fromPosition != toPosition) {
            listener.onRulesChanged(rules)
        }
    }

    /**
     * 处理规则移除
     * @param position 要移除的规则位置
     */
    internal fun onRuleRemove(position: Int) {
        rules.removeAt(position)

        notifyItemRemoved(position)

        // 之后所有项的标题需要重新编号。
        notifyItemRangeChanged(position, itemCount - position)

        listener.onRulesChanged(rules)
    }
}